package com.ruoyi.web.controller.system;

import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain.SysWhitePaperFile;
import com.ruoyi.system.minio.FileInfo;
import com.ruoyi.system.minio.MinioService;
import com.ruoyi.system.minio.PresignedUrlResponse;
import io.minio.StatObjectResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.net.URI;
import java.util.List;

@RestController
@RequestMapping("/system/oss/file")
public class FileController {
    protected final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private MinioService minioService;
    /**
     * 文件上传
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            String fileName = minioService.uploadFile(file);

            SysWhitePaperFile whitePaperFile = new SysWhitePaperFile();
            whitePaperFile.setFileUrl("/system/oss/file/download/" + fileName);
            whitePaperFile.setFileName(fileName);
            whitePaperFile.setOriginFileName(file.getOriginalFilename());

            return AjaxResult.success("文件上传成功", whitePaperFile);
        } catch (Exception e) {
            log.error("文件上传失败", e);

            return AjaxResult.error("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 文件下载
     */
    @Anonymous
    @GetMapping("/download/{fileName}")
    public ResponseEntity<byte[]> downloadFile(@PathVariable String fileName) {
        try {
            byte[] fileBytes = minioService.downloadFile(fileName);

            // 获取文件信息
            StatObjectResponse fileInfo = minioService.getFileInfo(fileName);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentLength(fileInfo.size());
            headers.setContentType(MediaType.parseMediaType(fileInfo.contentType()));
            headers.setContentDisposition(ContentDisposition.attachment()
                    .filename(fileName)
                    .build());

            return new ResponseEntity<>(fileBytes, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error("文件下载失败", e);
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 文件预览
     */
    @GetMapping("/preview/{fileName}")
    public AjaxResult previewFile(@PathVariable String fileName) {
        try {
            String previewUrl = minioService.getPreviewUrl(fileName);

            return AjaxResult.success("获取预览链接成功", previewUrl);
        } catch (Exception e) {
            log.error("获取预览链接失败", e);
            return AjaxResult.error("获取预览链接失败: " + e.getMessage());
        }
    }

    /**
     * 直接重定向到预览URL
     */
    @GetMapping("/view/{fileName}")
    public ResponseEntity<Void> viewFile(@PathVariable String fileName) {
        try {
            String previewUrl = minioService.getPreviewUrl(fileName);

            return ResponseEntity.status(HttpStatus.FOUND)
                    .location(URI.create(previewUrl))
                    .build();
        } catch (Exception e) {
            log.error("文件预览失败", e);
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 删除文件
     */
    @DeleteMapping("/delete/{fileName}")
    public AjaxResult deleteFile(@PathVariable String fileName) {
        try {
            minioService.deleteFile(fileName);

            return AjaxResult.success("文件删除成功");
        } catch (Exception e) {
            log.error("文件删除失败", e);
            return AjaxResult.error("文件删除失败: " + e.getMessage());
        }
    }

    /**
     * 获取文件列表
     */
    @GetMapping("/list")
    public AjaxResult listFiles() {
        try {
            List<String> files = minioService.listFiles();

            return AjaxResult.success("获取文件列表成功", files);
        } catch (Exception e) {
            log.error("获取文件列表失败", e);
            return AjaxResult.error("获取文件列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取文件信息
     */
    @GetMapping("/info/{fileName}")
    public AjaxResult getFileInfo(@PathVariable String fileName) {
        try {
            StatObjectResponse fileStat = minioService.getFileInfo(fileName);

            FileInfo fileInfo = new FileInfo();
            fileInfo.setFileName(fileName);
            fileInfo.setContentType(fileStat.contentType());
            fileInfo.setSize(fileStat.size());
            fileInfo.setLastModified(fileStat.lastModified().toLocalDateTime());
            fileInfo.setEtag(fileStat.etag());

            return AjaxResult.success("获取文件信息成功", fileInfo);
        } catch (Exception e) {
            log.error("获取文件信息失败", e);
            return AjaxResult.error("获取文件信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取前端直传URL
     */
    @GetMapping("/presigned-put-url")
    public AjaxResult getPresignedPutUrl(@RequestParam String fileName) {
        try {
            String url = minioService.getPresignedPutUrl(fileName);

            PresignedUrlResponse response = new PresignedUrlResponse();
            response.setFileName(fileName);
            response.setUrl(url);

            return AjaxResult.success("获取直传URL成功", response);
        } catch (Exception e) {
            log.error("获取直传URL失败", e);
            return AjaxResult.error("获取直传URL失败: " + e.getMessage());
        }
    }
}
